/* SOLMAIN.C */

#include <solipeg.g>
#include <solipeg.rsg>
#include <hwim.h>
#include <epoc.h>
#include <p_gen.h>

#define BORDER_WIDTH            6

GLREF_D PR_APPMAN * const       w_am ;
GLREF_D PR_WSERV *              w_ws ;
GLREF_D WSERV_SPEC *            wserv_channel ;
GLREF_D TEXT *                  DatCommandPtr ;
GLREF_D TEXT *                  DatApp1 ;

GLDEF_D PR_SOLENG *             soleng ; // Ptr to engine object

/************************************/
/* Solipeg Main Entry Point         */
/************************************/

GLDEF_C VOID main(VOID) {
    IN_HWIMMAN          app ;
    IN_WSERV            wserv ;

    p_linklib(0) ;
    app.flags = FLG_APPMAN_RSCFILE |
                    FLG_APPMAN_SRSCFILE |
                    FLG_APPMAN_CLEAN |
                    FLG_APPMAN_FULLSCREEN ;
    wserv.com_cat = app.wserv_cat = p_getlibh(CAT_SOLIPEG_SOLIPEG) ;
    app.wserv_class = C_SOLWS ;
    wserv.com_class = C_SOLCM ;
    p_send4(p_new(CAT_SOLIPEG_SOLIPEG, C_SOLAM), O_AM_INIT, &app, &wserv) ;
}


#pragma METHOD_CALL     // All the methods for WS/Window/AO follow


/******************************************/
/* Application Manager Subclass Method    */
/******************************************/

METHOD VOID solam_am_rscname(PR_SOLAM *self, TEXT *strName) {
    P_INFO      info ;

    p_atos(strName, "\\APP\\SOLIPEG\\SOLI%02d.RZC", p_getlanguage()) ;
    f_fparse(strName, DatCommandPtr, strName, NULL) ;
    if ( p_finfo(strName, &info) < 0 ) {
        p_supersend3(self, O_AM_RSCNAME, strName) ;
    }
}

/************************************/
/* Window Server Subclass Methods   */
/************************************/

METHOD VOID solws_ws_dyn_init(PR_SOLWS *self) {
    W_WINDATA       wd ;

    // This version will not run on S3 Classic
    if ( (wserv_channel->conn.info.version_id & WS_TYPE_MASK) != WS_TYPE_S3A ) {
        p_exit(hErrorDialog(E_GEN_NSUP, RS_S3AONLY)) ;
    }

    hLoadResource(RS_ENV, &DatApp1) ;

    // Create engine
    soleng = f_newsend(CAT_SOLIPEG_SOLIPEG, C_SOLENG, O_ENG_INIT) ;

    // Create window
    self->wserv.cli = f_new(CAT_SOLIPEG_SOLIPEG, C_SOLWIN) ;

    // Connect to window server with no backup bitmap
    wd.extent.tl.x = 0 ;
    wd.extent.tl.y = 0 ;
    wd.extent.width = wd.extent.height = wserv_channel->conn.info.pixels.y ;
    wd.background = W_WIN_BACK_NONE | W_WIN_BACK_GREY_NONE ;
    p_send5(    self->wserv.cli,
                O_WN_CONNECT,
                NULL,
                W_WIN_EXTENT | W_WIN_BACKGROUND,
                &wd) ;
    // Send the engine a NEW_GAME message
    p_send2(soleng, O_ENG_NEW_GAME) ;

    // Reposition the window
    p_send3(self->wserv.cli, O_WN_REPOS, soleng->soleng.winpos) ;

    // Make the window visible
    p_send3(self->wserv.cli, O_WN_VISIBLE, WV_INITVIS) ;

    // Make a Status bar visible
    wsEnable() ;

    // Show initial help dialog
    self->wserv.help_index_id = RH_MAIN ;
    p_send3(soleng, O_ENG_BEEP, RS_TITLE_SOUND) ;
    p_send3(self, O_WS_DO_HELP, RH_ABOUT) ;

    // Tell the engine to create a cursor, let the games begin
    p_send2(soleng, O_ENG_MAKE_CURSOR ) ;
}

/************************************/
/* Window Subclass Methods          */
/************************************/

// Reposition the window:
// uwPos = (0 == LEFT, 1 == CENTER, 2 == RIGHT)
METHOD VOID solwin_wn_repos(PR_SOLWIN *self, UWORD uwPos) {
    W_WINDATA       wd ;
    P_EXTENT        ext ;

    wInquireWindow(self->win.id, &wd) ;
    wInquireStatusWindow(W_STATUS_WINDOW_BIG, &ext) ;
    if ( uwPos == 0 ) {
        wd.extent.tl.x = 0 ;
    }
    else if ( uwPos == 1 ) {
        wd.extent.tl.x = (  wserv_channel->conn.info.pixels.x -
                            wd.extent.width ) / 2 ;
    }
    else {
        wd.extent.tl.x =    wserv_channel->conn.info.pixels.x -
                            wd.extent.width -
                            ext.width ;
    }
    wSetWindow( w_ws->wserv.cli->win.id,
                W_WIN_EXTENT,
                &wd ) ;
    p_send3(soleng, O_ENG_SETCURSOR, wd.extent.tl.x) ;
}

// REPLACEment for the WN_REDRAW method, which clears some rectangles
// as necessary
METHOD VOID solwin_wn_redraw(PR_SOLWIN *self, P_RECT *rectRedraw) {
    W_WINDATA   wd ;
    P_RECT      rect ;
    G_GC        gc ;

    gc.flags = G_GC_FLAG_BOTH_PLANES ;
    wBeginRedrawGC(self->win.id, rectRedraw, G_GC_MASK_GREY, &gc) ;

    wInquireWindow(self->win.id, &wd) ;

    // TOP
    rect.tl.x = rect.tl.y = 0 ;
    rect.br.x = wd.extent.width ;
    rect.br.y = BORDER_WIDTH ;
    if ( p_intrec(&rect, rectRedraw, &rect) ) {
        gClrRect(&rect, G_TRMODE_CLR) ;
    }

    // LHS
    rect.tl.x = rect.tl.y = 0 ;
    rect.br.x = BORDER_WIDTH ;
    rect.br.y = wd.extent.height ;
    if ( p_intrec(&rect, rectRedraw, &rect) ) {
        gClrRect(&rect, G_TRMODE_CLR) ;
    }

    // BOT
    rect.tl.x = 0 ;
    rect.tl.y = wd.extent.height - BORDER_WIDTH ;
    rect.br.x = wd.extent.width ;
    rect.br.y = wd.extent.height ;
    if ( p_intrec(&rect, rectRedraw, &rect) ) {
        gClrRect(&rect, G_TRMODE_CLR) ;
    }

    // RHS
    rect.tl.x = wd.extent.width - BORDER_WIDTH ;
    rect.tl.y = 0 ;
    rect.br.x = wd.extent.width ;
    rect.br.y = wd.extent.height ;
    if ( p_intrec(&rect, rectRedraw, &rect) ) {
        gClrRect(&rect, G_TRMODE_CLR) ;
    }

    p_send2(self, O_WN_DRAW) ;
    wEndRedraw() ;
}

// Pass the key stroke to the engine
METHOD VOID solwin_wn_key(PR_SOLWIN *self, INT keycode, INT mods) {
    p_send4(soleng, O_ENG_KEY, keycode, mods) ;
}

// Draw the window - border and board
METHOD VOID solwin_wn_draw(PR_SOLWIN *self) {
    gBorder2(W_BORDER_TYPE_1, W_BORD_CORNER_1 | W_BORD_SHADOW_ON) ;
    p_send2(soleng, O_ENG_DRAW_BOARD) ;
}

/************************************/
/* Active Object Subclass Methods   */
/************************************/

// Simple REPLACEment for the AO_INIT method
METHOD VOID waveao_ao_init(PR_WAVEAO *self) {
    self->active.priority = PRIORITY_ACTIVE_VOICE ;
    p_send3(w_am, O_AM_ADD_TASK, self) ;
}

// Simple REPLACEment for the AO_CANCEL method
METHOD VOID waveao_ao_cancel(PR_WAVEAO *self) {
    p_playsoundcancel() ;
    p_supersend2(self, O_AO_CANCEL) ;
}

// ADDition of a WV_PLAY method
METHOD VOID waveao_wv_play( PR_WAVEAO * self,
                            TEXT *      name,
                            UINT        volume ) {
    if ( !self->active.isactive ) {
        p_playsounda(name, 0, volume, &self->active.stat) ;
        self->active.isactive = TRUE ;
    }
}


